package com.example.foo.ftt.service;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.foo.UserLevelEnum;
import com.example.core.PageResult;
import com.example.core.Pageable;
import com.example.foo.ftt.model.FttUser;
import com.example.foo.ftt.query.FttUserQuery;
import com.example.foo.ftt.FttLevel;
import com.example.foo.ftt.dao.FttUserDao;

@org.springframework.stereotype.Service
public class FttUserService {

	private final FttUserDao fttUserDao;

	public FttUserService(FttUserDao fttUserDao) {
		this.fttUserDao = fttUserDao;
	}

	// ========== FttUser ==========

	public PageResult<FttUser> findFttUsers(FttUserQuery fttUserQuery, Pageable pageable) {
		return fttUserDao.findFttUsers(fttUserQuery, pageable);
	}

	public List<FttUser> findFttUsersByIds(List<Long> ids) {
		return fttUserDao.selectBatchIds(ids);
	}

	public FttUser findFttUserById(Long id) {
		return fttUserDao.selectById(id);
	}

	public FttUser findFttUserByUserId(Long userId) {
		return fttUserDao.selectOne(new QueryWrapper<FttUser>()
				.eq("user_id", userId)
				);
	}

	public List<FttUser> findFttUsersByUserIds(List<Long> userIds) {
		if (userIds.isEmpty()) {
			return Collections.emptyList();
		}
		return fttUserDao.selectList(new QueryWrapper<FttUser>()
				.in("user_id", userIds)
				);
	}

	public Map<Long, FttUser> findFttUsersByUserIdsAsMap(List<Long> userIds) {
		List<FttUser> fttUsers = findFttUsersByUserIds(userIds);
		Map<Long, FttUser> result = new HashMap<>(fttUsers.size());
		for (FttUser t : fttUsers) {
			result.put(t.getUserId(), t);
		}
		return result;
	}

	public FttUser findFttUserByCellphone(String cellphone) {
		return fttUserDao.selectOne(new QueryWrapper<FttUser>()
				.eq("cellphone", cellphone)
				);
	}

	public FttUser findFttUserByReferralCode(String referralCode) {
		return fttUserDao.selectOne(new QueryWrapper<FttUser>()
				.eq("referral_code", referralCode)
				);
	}

	public boolean findFttUserCountExistByReferralCode(String referralCode) {
		return fttUserDao.selectCount(new QueryWrapper<FttUser>()
				.eq("referral_code", referralCode)
				) > 0;
	}

	public List<FttUser> findFttUsersByParentUserId(Long parentUserId) {
		return fttUserDao.selectList(new QueryWrapper<FttUser>()
				.eq("parent_user_id", parentUserId)
				);
	}

	public Long findFttUserCountByParentUserId(Long parentUserId) {
		return fttUserDao.selectCount(new QueryWrapper<FttUser>()
				.eq("parent_user_id", parentUserId)
				);
	}

	public Long findFttUserCountByReferralParentUserId(Long referralParentUserId) {
		return fttUserDao.selectCount(new QueryWrapper<FttUser>()
				.eq("referral_parent_user_id", referralParentUserId)
				);
	}

	public Long findFttUserCountByParentUserIdPathLikeRight(String parentUserIdPath) {
		return fttUserDao.selectCount(new QueryWrapper<FttUser>()
				.likeRight("parent_user_id_path", parentUserIdPath)
				);
	}

	public List<String> findFttUserFttLevelsByParentUserIdPathLikeRight(String parentUserIdPath) {
		return fttUserDao.findFttUserFttLevelsByParentUserIdPathLikeRight(parentUserIdPath);
	}

	public Long findFttUserCountByStateAndFttLevel(FttUser.State state, FttLevel fttLevel) {
		return fttUserDao.selectCount(new QueryWrapper<FttUser>()
				.eq("state", state)
				.eq("ftt_level", fttLevel)
				);
	}

	public FttUser findFttUserByCardzCellphone(String cardzCellphone) {
		return fttUserDao.selectOne(new QueryWrapper<FttUser>()
				.eq("cardz_cellphone", cardzCellphone)
				);
	}

	public FttUser createFttUser(String cellphone, String referralCode, Long referralParentUserId, String referralParentUserIdPath, Long userId) {
		FttUser fttUser = new FttUser();
		fttUser.setState(FttUser.State.normal);
		fttUser.setRoleLevel(UserLevelEnum.L_2_0.levelId);
		fttUser.setFttLevel(FttLevel.F0);
		fttUser.setCellphone(cellphone);
		fttUser.setReferralCode(referralCode);
		fttUser.setReferralParentUserId(referralParentUserId);
		fttUser.setReferralParentUserIdPath(referralParentUserIdPath);
		fttUser.setParentUserId(0L);
		fttUser.setParentUserIdPath("/");
		fttUser.setMemo("");
		fttUser.setUserId(userId);
		fttUser.setIdname("");
		fttUser.setCardzState(FttUser.CardzState.pending);
		fttUser.setCardzCellphone("");
		fttUser.setCreatedAt(LocalDateTime.now());
		fttUserDao.insert(fttUser);
		return fttUser;
	}

	public void updateFttUserState(Long id, FttUser.State state, String memo) {
		FttUser fttUser = new FttUser();
		fttUser.setId(id);
		fttUser.setState(state);
		fttUser.setMemo(memo);
		fttUser.setUpdatedAt(LocalDateTime.now());
		fttUserDao.updateById(fttUser);
	}

	public void updateFttUserRoleLevel(Long id, UserLevelEnum roleLevel) {
		FttUser fttUser = new FttUser();
		fttUser.setId(id);
		fttUser.setRoleLevel(roleLevel.levelId);
		fttUser.setUpdatedAt(LocalDateTime.now());
		fttUserDao.updateById(fttUser);
	}

	public void updateFttUserFttLevel(Long id, FttLevel fttLevel) {
		FttUser fttUser = new FttUser();
		fttUser.setId(id);
		fttUser.setFttLevel(fttLevel);
		fttUser.setUpdatedAt(LocalDateTime.now());
		fttUserDao.updateById(fttUser);
	}

	public void updateFttUserCellphone(Long id, String cellphone) {
		FttUser fttUser = new FttUser();
		fttUser.setId(id);
		fttUser.setCellphone(cellphone);
		fttUser.setUpdatedAt(LocalDateTime.now());
		fttUserDao.updateById(fttUser);
	}

	public void updateFttUserParents(Long id, Long parentUserId, String parentUserIdPath) {
		FttUser fttUser = new FttUser();
		fttUser.setId(id);
		fttUser.setParentUserId(parentUserId);
		fttUser.setParentUserIdPath(parentUserIdPath);
		fttUser.setUpdatedAt(LocalDateTime.now());
		fttUserDao.updateById(fttUser);
	}

	public void updateFttUserIdname(Long id, String idname) {
		FttUser fttUser = new FttUser();
		fttUser.setId(id);
		fttUser.setIdname(idname);
		fttUser.setUpdatedAt(LocalDateTime.now());
		fttUserDao.updateById(fttUser);
	}

	public void updateFttUserCardz(Long id, FttUser.CardzState cardzState, String cardzCellphone) {
		FttUser fttUser = new FttUser();
		fttUser.setId(id);
		fttUser.setCardzState(cardzState);
		fttUser.setCardzCellphone(cardzCellphone);
		fttUser.setUpdatedAt(LocalDateTime.now());
		fttUserDao.updateById(fttUser);
	}

	public void deleteFttUserById(Long id) {
		fttUserDao.deleteById(id);
	}

}
